package com.ben.utils.appinfo

import android.app.ActivityManager
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.text.TextUtils
import com.ben.utils.ext.tryCatch
import java.io.BufferedReader
import java.io.FileReader
import java.lang.Exception

/**
 * Author: liliangyi
 * Maintainer: liliangyi
 * Date: 2019/6/29 0029
 * Copyright: 2019  Inc. All rights reserved.
 * Desc:
 */
object AppInfoUtils {

    /**
     * 获取所有包含launcher属性的app的包名
     *
     * @param context
     * @return
     */
    fun getInstalledLauncherApps(context: Context): List<String> {
        val apps = mutableListOf<String>()
        tryCatch {
            val mainIntent = Intent(Intent.ACTION_MAIN, null)
            mainIntent.addCategory(Intent.CATEGORY_LAUNCHER)
            val resolveApps = context.applicationContext
                .packageManager
                .queryIntentActivities(mainIntent, 0)
            for (resolveApp in resolveApps) {
                apps.add(resolveApp.activityInfo.packageName)
            }
        }
        return apps
    }

    /**
     * 通过包名判断是否为系统集成app
     *
     * @param context
     * @param pkgName app包名
     * @return
     */
    fun isSystemApp(context: Context, pkgName: String?): Boolean {
        tryCatch {
            val pInfo = context.applicationContext.packageManager.getPackageInfo(pkgName!!, 0)
            return pInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0 ||
                pInfo.applicationInfo.flags and ApplicationInfo.FLAG_UPDATED_SYSTEM_APP != 0
        }
        return false
    }

    /**
     * 获取安装的系统app列表
     *
     * @param context
     * @return
     */
    fun getSystemApps(context: Context): List<String> {
        val apps = getInstalledLauncherApps(context)
        val sysApps = mutableListOf<String>()
        for (app in apps) {
            if (isSystemApp(context, app)) {
                sysApps.add(app)
            }
        }
        return sysApps
    }

    /**
     * 是否为更新过后的系统应用
     *
     * @param mContext
     * @param pkgName  包名
     * @return
     */
    fun isUpdatedSysApp(mContext: Context, pkgName: String?): Boolean {
        pkgName ?: return false
        tryCatch {
            val info = mContext.applicationContext
                .packageManager
                .getApplicationInfo(pkgName, PackageManager.GET_META_DATA)
            return info.flags and ApplicationInfo.FLAG_UPDATED_SYSTEM_APP != 0
        }
        return false
    }

    /**
     * 通过包名获取app图标
     *
     * @param context
     * @param packageName
     * @return
     */
    fun getAppIconByPkgName(context: Context, pkgName: String?): Drawable? {
        pkgName ?: return null
        tryCatch {
            val packageManager = context.applicationContext.packageManager
            val info =
                packageManager.getApplicationInfo(pkgName, PackageManager.GET_META_DATA)
            packageManager.getApplicationIcon(info)
            return info.loadIcon(packageManager)
        }
        return null
    }

    /**
     * 通过包名获取app名字
     *
     * @param context
     * @param packageName
     * @return
     */
    fun getAppNameByPkgName(context: Context, packageName: String?): String? {
        tryCatch {
            val packageManager = context.applicationContext.packageManager
            val info =
                packageManager.getApplicationInfo(packageName!!, PackageManager.GET_META_DATA)
            return info.loadLabel(packageManager).toString()
        }
        return null
    }

    /**
     * 判断app是否安装
     *
     * @param context
     * @param pkgName
     * @return
     */
    fun isInstalled(context: Context?, pkgName: String?): Boolean {
        context ?: return false
        return if (pkgName.isNullOrEmpty()) {
            false
        } else try {
            context.packageManager.getPackageInfo(pkgName, 0) != null
        } catch (e: Exception) {
            false
        }
    }

    /**
     * 获取程序的版本名称
     *
     * @param context
     * @param pkgName
     * @return
     */
    fun getAppVersion(context: Context, pkgName: String): String? {
        tryCatch {
            // 包管理操作管理类
            val pm = context.applicationContext.packageManager
            val packInfo = pm.getPackageInfo(pkgName, 0)
            return packInfo.versionName
        }
        return null
    }

    /**
     * 获取程序的版本号
     *
     * @param context
     * @param pkgName
     * @return
     */
    fun getAppVersionCode(context: Context, pkgName: String?): Int {
        pkgName ?: return 0
        tryCatch {
            // 包管理操作管理类
            val pm = context.applicationContext.packageManager
            return pm.getPackageInfo(pkgName, 0).versionCode
        }
        return 0
    }

    /**
     * 获取正在运行的activity名称
     *
     * @param mContext
     * @return
     */
    fun getRunningActivityName(mContext: Context): String? {
        tryCatch {
            val activityManager = mContext.applicationContext
                .getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
            return activityManager.getRunningTasks(1)[0].topActivity!!.className
        }
        return null
    }

    /**
     * 获取进程号对应的进程名
     *
     * @param pid 进程号
     * @return 进程名
     */
    fun getProcessName(pid: Int): String? {
        tryCatch {
            BufferedReader(FileReader("/proc/$pid/cmdline")).use { reader ->
                var processName = reader.readLine()
                if (!TextUtils.isEmpty(processName)) {
                    processName = processName.trim { it <= ' ' }
                }
                return processName
            }
        }
        return null
    }

    /**
     * 获取application中指定的meta-data。例如，调用方法时key就是UMENG_CHANNEL
     *
     * @return 如果没有获取成功(没有对应值 ， 或者异常)，则返回值为空
     */
    fun getAppMetaData(context: Context, key: String?): String? {
        if (key.isNullOrEmpty()) {
            return null
        }
        tryCatch {
            val packageManager = context.applicationContext.packageManager
            if (packageManager != null) {
                val applicationInfo = packageManager.getApplicationInfo(
                    context.packageName, PackageManager.GET_META_DATA
                )
                if (applicationInfo != null) {
                    if (applicationInfo.metaData != null) {
                        return applicationInfo.metaData.getString(key)
                    }
                }
            }
        }
        return null
    }

    /**
     * 通过包名获取packageInfo
     * @param context
     * @param pkgName
     * @return
     */
    @JvmStatic
    fun getPackageInfo(context: Context, pkgName: String?): PackageInfo? {
        return if (pkgName.isNullOrEmpty()) {
            null
        } else try {
            context.packageManager.getPackageInfo(pkgName, 0)
        } catch (e: Exception) {
            null
        }
    }
}
